<template>
  <teleport to="body">
    <div
      v-if="visible"
      ref="menuRef"
      :class="['context-menu', { 'scrollable': needsScroll }]"
      :style="menuStyle"
      @click.stop
      @contextmenu="handleContextMenuEvent"
    >
      <div class="context-menu-content">
        <template v-for="(item, index) in items" :key="item.name">
          <div
            v-if="!item.children || item.children.length === 0"
            :class="[
              'context-menu-item',
              {
                'context-menu-item--disabled': item.disabled
              }
            ]"
            @click="handleItemClick(item)"
          >
            <div class="context-menu-item__content">
              <q-icon
                v-if="item.icon"
                :name="item.icon"
                class="context-menu-item__icon"
              />
              <span class="context-menu-item__title">{{ item.title }}</span>
              <span
                v-if="item.shortcuts"
                class="context-menu-item__shortcuts"
              >
                {{ item.shortcuts }}
              </span>
            </div>
          </div>
          
          <!-- 子菜单项 -->
          <div
            v-else
            :class="[
              'context-menu-item',
              'context-menu-item--submenu',
              {
                'context-menu-item--disabled': item.disabled
              }
            ]"
            @mouseenter="handleSubmenuHover(index)"
            @mouseleave="handleSubmenuLeave"
          >
            <div class="context-menu-item__content">
              <q-icon
                v-if="item.icon"
                :name="item.icon"
                class="context-menu-item__icon"
              />
              <span class="context-menu-item__title">{{ item.title }}</span>
              <q-icon
                name="chevron_right"
                class="context-menu-item__arrow"
              />
            </div>
            
            <!-- 子菜单 -->
            <div
              v-if="hoveredSubmenuIndex === index"
              class="context-submenu"
              :style="submenuStyle"
              @mouseenter="handleSubmenuHover(index)"
              @mouseleave="handleSubmenuLeave"
            >
              <div
                v-for="subItem in item.children"
                :key="subItem.name"
                :class="[
                  'context-menu-item',
                  {
                    'context-menu-item--disabled': subItem.disabled
                  }
                ]"
                @click="handleItemClick(subItem)"
              >
                <div class="context-menu-item__content">
                  <q-icon
                    v-if="subItem.icon"
                    :name="subItem.icon"
                    class="context-menu-item__icon"
                  />
                  <span class="context-menu-item__title">{{ subItem.title }}</span>
                  <span
                    v-if="subItem.shortcuts"
                    class="context-menu-item__shortcuts"
                  >
                    {{ subItem.shortcuts }}
                  </span>
                </div>
              </div>
            </div>
          </div>
        </template>
      </div>
    </div>
  </teleport>
</template>

<script setup lang="ts">
import { ref, computed, nextTick, onMounted, onUnmounted, watch } from 'vue';
import type { MenuItem, MenuPosition } from '../types/node';

interface Props {
  visible: boolean;
  position: MenuPosition;
  items: MenuItem[];
  targetData?: any;
}

interface Emits {
  (e: 'close'): void;
  (e: 'item-click', item: MenuItem, targetData?: any): void;
}

const props = withDefaults(defineProps<Props>(), {
  visible: false,
  items: () => [],
});

const emit = defineEmits<Emits>();

const menuRef = ref<HTMLElement>();

// 调整后的菜单位置
const adjustedPosition = ref<MenuPosition>({ x: 0, y: 0 });
const isPositionAdjusted = ref(false);
const needsScroll = ref(false);

// 当前悬停的子菜单索引
const hoveredSubmenuIndex = ref<number>(-1);

// 子菜单隐藏定时器
let submenuHideTimer: number | null = null;

// 计算菜单位置样式
const menuStyle = computed(() => {
  const position = isPositionAdjusted.value ? adjustedPosition.value : props.position;
  return {
    position: 'fixed' as const,
    left: `${position.x}px`,
    top: `${position.y}px`,
    zIndex: 9999,
  };
});

// 计算子菜单位置样式
const submenuStyle = computed(() => {
  return {
    position: 'absolute' as const,
    left: '100%',
    top: '0',
    zIndex: 10000,
  };
});



// 处理菜单项点击
const handleItemClick = (item: MenuItem) => {
  if (item.disabled) return;

  emit('item-click', item, props.targetData);
  emit('close');
};

// 处理子菜单hover
const handleSubmenuHover = (index: number) => {
  // 清除隐藏定时器
  if (submenuHideTimer) {
    clearTimeout(submenuHideTimer);
    submenuHideTimer = null;
  }
  hoveredSubmenuIndex.value = index;
};

// 处理子菜单离开
const handleSubmenuLeave = () => {
  // 延迟隐藏子菜单，给用户时间移动到子菜单
  submenuHideTimer = setTimeout(() => {
    hoveredSubmenuIndex.value = -1;
  }, 150);
};

// 键盘导航处理
const handleKeydown = (event: KeyboardEvent) => {
  if (!props.visible) return;

  switch (event.key) {
    case 'Escape':
      emit('close');
      break;
  }
};

// 点击外部区域关闭菜单
const handleClickOutside = (event: MouseEvent) => {
  if (!props.visible) return;

  const target = event.target as HTMLElement;
  if (menuRef.value && !menuRef.value.contains(target)) {
    emit('close');
  }
};

// 处理菜单自身的右键点击事件
const handleContextMenuEvent = (event: MouseEvent) => {
  // 阻止菜单自身的右键菜单
  event.preventDefault();
  event.stopPropagation();
};

// 调整菜单位置以防止超出视窗
const adjustMenuPosition = async () => {
  if (!props.visible || !menuRef.value) return;

  await nextTick();

  const menu = menuRef.value;

  // 重置菜单样式，确保每次计算都是基于原始状态
  menu.style.maxHeight = '';
  menu.style.overflowY = '';
  needsScroll.value = false;

  // 等待DOM更新完成，获取菜单的自然尺寸
  const rect = menu.getBoundingClientRect();
  const viewportWidth = window.innerWidth;
  const viewportHeight = window.innerHeight;

  // 使用当前的位置作为基准（可能是调整后的位置或原始位置）
  let { x, y } = isPositionAdjusted.value ? adjustedPosition.value : props.position;

  // 获取菜单的实际尺寸（自然高度）
  const menuWidth = rect.width;
  const menuHeight = rect.height;

  // 设置安全边距
  const margin = 10;

  // 水平位置调整
  if (x + menuWidth > viewportWidth - margin) {
    // 如果右侧空间不足，尝试显示在鼠标左侧
    const leftSpace = x - margin;
    if (leftSpace >= menuWidth) {
      x = x - menuWidth;
    } else {
      // 左右都不够，贴右边显示
      x = viewportWidth - menuWidth - margin;
    }
  }

  // 垂直位置调整 - 关键优化
  const bottomSpace = viewportHeight - y - margin;
  const topSpace = y - margin;

  let needsHeightAdjustment = false;
  let maxHeight = 0;

  // 检查菜单是否需要调整位置或高度
  if (menuHeight > bottomSpace) {
    // 下方空间不足
    if (topSpace >= menuHeight) {
      // 上方空间足够完整显示菜单，移到上方
      y = y - menuHeight;
    } else {
      // 上下都不够完整显示，选择空间更大的一侧
      if (topSpace > bottomSpace) {
        // 上方空间更大，移到上方并限制高度
        y = margin;
        needsHeightAdjustment = true;
        maxHeight = topSpace - margin; // 留出一些边距
      } else {
        // 下方空间更大或相等，保持在下方并限制高度
        needsHeightAdjustment = true;
        maxHeight = bottomSpace - margin; // 留出一些边距
      }
    }
  }
  // 如果下方空间足够，不需要任何调整

  // 确保不超出左边界
  if (x < margin) {
    x = margin;
  }

  // 确保不超出上边界
  if (y < margin) {
    y = margin;
  }

  // 更新响应式位置数据
  adjustedPosition.value = { x, y };
  isPositionAdjusted.value = true;

  // 应用高度限制（如果需要）
  if (needsHeightAdjustment && maxHeight > 0) {
    needsScroll.value = true;
    await nextTick(); // 等待位置更新后再设置高度
    menu.style.maxHeight = `${maxHeight}px`;
  }


};



// 监听可见性变化
const handleVisibilityChange = () => {
  if (props.visible) {
    isPositionAdjusted.value = false; // 重置位置调整状态
    needsScroll.value = false; // 重置滚动状态
    hoveredSubmenuIndex.value = -1; // 重置子菜单状态
    // 延迟调整位置，确保菜单已渲染
    nextTick(() => {
      adjustMenuPosition();
    });
  } else {
    // 菜单隐藏时重置状态
    isPositionAdjusted.value = false;
    needsScroll.value = false;
    hoveredSubmenuIndex.value = -1;

    // 清理子菜单定时器
    if (submenuHideTimer) {
      clearTimeout(submenuHideTimer);
      submenuHideTimer = null;
    }

    if (menuRef.value) {
      menuRef.value.style.maxHeight = '';
      menuRef.value.style.overflowY = '';
    }
  }
};

onMounted(() => {
  document.addEventListener('click', handleClickOutside);
  document.addEventListener('keydown', handleKeydown);
  handleVisibilityChange();
});

onUnmounted(() => {
  document.removeEventListener('click', handleClickOutside);
  document.removeEventListener('keydown', handleKeydown);

  // 清理子菜单定时器
  if (submenuHideTimer) {
    clearTimeout(submenuHideTimer);
    submenuHideTimer = null;
  }
});

// 监听 visible 属性变化
watch(() => props.visible, handleVisibilityChange);

// 监听 position 属性变化，支持连续右键触发
watch(() => props.position, (newPosition, oldPosition) => {
  // 只有在菜单可见且位置确实发生变化时才重新调整
  if (props.visible && oldPosition &&
      (newPosition.x !== oldPosition.x || newPosition.y !== oldPosition.y)) {

    // 重置位置调整状态，使用新的位置
    isPositionAdjusted.value = false;
    needsScroll.value = false;

    // 立即调整位置
    nextTick(() => {
      adjustMenuPosition();
    });
  }
}, { deep: true, immediate: false });
</script>

<style scoped>
.context-menu {
  background: white;
  border: 1px solid #e0e0e0;
  border-radius: 6px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  min-width: 180px;
  max-width: 300px;
  /* overflow: hidden; */
  user-select: none;
  /* 确保菜单不会被其他元素遮挡 */
  pointer-events: auto;
  /* 默认不设置固定高度，让内容决定高度 */
}

/* 只有当设置了最大高度时才启用滚动 */
.context-menu.scrollable {
  overflow-y: auto;
}

/* 自定义滚动条样式 - 只在可滚动时应用 */
.context-menu.scrollable::-webkit-scrollbar {
  width: 6px;
}

.context-menu.scrollable::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 3px;
}

.context-menu.scrollable::-webkit-scrollbar-thumb {
  background: #c1c1c1;
  border-radius: 3px;
}

.context-menu.scrollable::-webkit-scrollbar-thumb:hover {
  background: #a8a8a8;
}

.context-menu-content {
  padding: 4px 0;
}

.context-menu-item {
  position: relative;
  padding: 0;
  margin: 0;
  cursor: pointer;
  transition: background-color 0.15s ease;
}

.context-menu-item:hover:not(.context-menu-item--disabled) {
  background-color: #f5f5f5;
}

.context-menu-item--disabled {
  cursor: not-allowed;
  opacity: 0.5;
}

.context-menu-item__content {
  display: flex;
  align-items: center;
  padding: 8px 12px;
  gap: 8px;
}

.context-menu-item__icon {
  font-size: 16px;
  color: #666;
  flex-shrink: 0;
}

.context-menu-item__title {
  flex: 1;
  font-size: 14px;
  color: #333;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.context-menu-item__shortcuts {
  font-size: 12px;
  color: #999;
  flex-shrink: 0;
}

.context-menu-item__arrow {
  font-size: 16px;
  color: #666;
  flex-shrink: 0;
}

.context-menu-item--submenu {
  position: relative;
}

.context-submenu {
  background: white;
  border: 1px solid #e0e0e0;
  border-radius: 6px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  min-width: 160px;
  overflow: hidden;
  padding: 4px 0;
}

.context-submenu .context-menu-item:hover:not(.context-menu-item--disabled) {
  background-color: #f5f5f5;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .context-menu {
    min-width: 160px;
    max-width: 250px;
  }

  .context-menu-item__content {
    padding: 10px 12px;
  }

  .context-menu-item__title {
    font-size: 16px;
  }
}
</style>
